package org.l.qiao;

import org.apache.log4j.Logger;
import org.l.qiao.base.Convert;
import org.l.qiao.base.UnknowLTypeException;

import java.lang.reflect.Field;
import java.util.*;


/**
 * Created by 严秋旺 on 2015/1/14.
 */
public class ClusterUtil {
    private static final Logger LOGGER = Logger.getLogger(ClusterUtil.class);

    public static void put(Cluster cluster, String keyPath, KeyType keyType, Object value) {
        switch (keyType) {
            case ListKey:
                putList(cluster, keyPath, value);
                break;
            default:
                putMap(cluster, keyPath, value);
        }
    }

    /**
     * 添加或设置键值
     *
     * @param cluster 待添加数据簇
     * @param keyPath 添加路径
     * @param value   添加值
     */
    public static void putMap(Cluster cluster, String keyPath, Object value) {
        String[] paths = keyPath.split("\\.");
        Map tmpMap = cluster;
        int i = 0;
        for (i = 0; i < paths.length - 2; i++) {
            Object object = tmpMap.get(paths[i]);
            if (object != null && object instanceof Map) {
                tmpMap = (Map) object;
            } else {
                Map map = new HashMap();
                tmpMap.put(paths[i], map);
                tmpMap = map;
            }
        }
        tmpMap.put(paths[i], value);
    }

    /**
     * 添加列表值
     *
     * @param cluster 待添加数据簇
     * @param keyPath 添加路径
     * @param value   添加值
     */
    public static void putList(Cluster cluster, String keyPath, Object value) {
        String[] paths = keyPath.split("\\.");
        Map tmpMap = cluster;
        int i = 0;
        for (i = 0; i < paths.length - 2; i++) {
            Object object = tmpMap.get(paths[i]);
            if (object != null && object instanceof Map) {
                tmpMap = (Map) object;
            } else {
                Map map = new HashMap();
                tmpMap.put(paths[i], map);
                tmpMap = map;
            }
        }
        Object object = tmpMap.get(paths[i]);
        if (object != null && object instanceof List) {
            ((List) object).add(value);
        } else {
            List<Object> list = new ArrayList<>();
            list.add(value);
            tmpMap.put(paths[i], list);
        }
    }

    /**
     * 键值检查
     *
     * @param clusterClass 数据簇类
     * @param keyName      键名
     * @param value        值
     * @return 值合法则返回true, 否则返回false
     */
    public static boolean checkValue(Class clusterClass, String keyName, String value) {
        boolean result = false;
        try {
            Field field = clusterClass.getField(keyName);
            Key annotation = field.getAnnotation(Key.class);
            if (annotation == null) {
                result = true;
            } else {
                result = Validate.check(annotation.check(), value);
            }
        } catch (NoSuchFieldException e) {
            LOGGER.error("键名不存在[" + keyName + "]：" + e);
        }
        return result;
    }

    /**
     * 获取键值
     *
     * @param clusterClass 数据簇类
     * @param key          键名
     * @return 返回键值
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    public static String getKey(Class clusterClass, String key) throws NoSuchFieldException, IllegalAccessException {
        Field field = clusterClass.getField(key);
        return field.get(null).toString();
    }

    /**
     * 键值转换
     *
     * @param clusterClass 数据簇类
     * @param key          键名
     * @param value        值
     * @return 换换后的值对象
     * @throws Exception
     */
    public static Object parseValue(Class clusterClass, String key, String value) throws NoSuchFieldException, UnknowLTypeException {
        Field field = clusterClass.getField(key);
        Key annotation = field.getAnnotation(Key.class);
        return Convert.parse(annotation, value);
    }

    /**
     * 获取数据簇的检查对象
     *
     * @param clusterClass 数据簇
     * @return 返回各键值的检查对象集合
     */
    public static Cluster getCheck(Class clusterClass) {
        Cluster checkMap = new Cluster();
        Field[] fields = clusterClass.getFields();
        for (Field field : fields) {
            Key annotation = field.getAnnotation(Key.class);
            if (annotation != null) {
                try {
                    checkMap.put(field.get(null).toString(), annotation.check());
                } catch (IllegalAccessException e) {
                    LOGGER.error("键值获取异常[" + field.getName() + "]：" + e);
                }
            }
        }
        return checkMap;
    }

    public static void extend(Map source, Map map) {
        Iterator iterator = map.entrySet().iterator();

        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            Object key = entry.getKey();
            Object src = source.get(entry.getKey());
            Object dest = entry.getValue();

            if (dest instanceof Map && src instanceof Map) {
                extend((Map) src, (Map) dest);
            } else {
                source.put(key, dest);
            }

        }
    }

}
